#light

open MPITools
open System.Data
open Microsoft.FSharp.Math            
     
MPI.initialize()

let procSize = MPI.size()
let curProcess =  MPI.rank()
if curProcess = 0 then printf "initialisation complete\n"

printf "Rank: %d   Size : %d\n" curProcess  procSize
   
let pingpong n =
    if curProcess = 0 then
        let mutable  a=  0
        for i = 0 to n do
            MPI.send(i,1,0)
            let b = MPI.receive<int>(1,0)            
            printf "%d\n" b
        done
        
    elif curProcess = 1 then        
        for i = 0 to n do
            let b = MPI.receive<int>(0,0)
            MPI.send(b+1,0,0)            
        done

let funcTest () =
    if curProcess = 0 then
        let f = fun x -> 1332 + x
        MPI.send(f,1,0)                        
        let a = MPI.receive<int>(1,0)        
        printf "%d" a
    elif curProcess = 1 then
        
        let f = MPI.receive<(int->int)>(0,0)
        
        let x = f 5
        MPI.send(x,0,0)        
    
let genDataSet nRows = 
    let data = new DataSet("zoo")
    let table = data.Tables.Add("test2")
    let col1 = table.Columns.Add("n")
    let col2 = table.Columns.Add("c")
    
    for i = 0 to nRows-1 do
        let row = table.NewRow()
        //row.[col1] <- 1
        
        row.set_Item(col1,1)
        row.set_Item(col2,"a" + i.ToString())
        table.Rows.Add(row)
    done
    data
let sendreceiveDataSet () =     
    let t = genDataSet 500
    if curProcess = 0 then MPI.send(t,1,0)
    
    elif curProcess = 1 then  printf "Rows %d" ((MPI.receive<DataSet>(0,0)).Tables.get_Item(0).Rows.Count)

let sendreceiveMatrix () =        
    if curProcess = 0 then 
        let m1 = Matrix.create 50 20 1.0 |> Matrix.randomize
        MPI.send(m1,1,0)
        let m2 = MPI.receive<matrix>(1,0)        
        assert(m1=m2)
        printf "ok"
    elif curProcess = 1 then
        let n = MPI.receive<matrix>(0,0)
        MPI.send(n,0,0)        
        printf "d %d %d" (n.NumRows) (n.NumCols)

let sendreceiveArray() =
    if curProcess =0 then 
        let arr = Array.init 22 (fun i -> i *2) 
        MPI.sendArray(arr,1,0)
        
    else
        
        let nArr = MPI.receiveArray<int>(0,0)        
        nArr |> Array.iter (fun i -> printf "%d\n" i )
        
let sendreceiveArrayDD() =
    if curProcess =0 then 
        printf "dataset samples"
        let arr = Array.init 22 (fun i -> genDataSet i) 
        MPI.sendArray(arr,1,0)
        
    else
        
        let nArr = MPI.receiveArray<DataSet>(0,0)        
        nArr |> Array.iter (fun i -> printf " %d\n" (i.Tables.get_Item(0).Rows.Count))
    
let sendreceiveMatrix2 () =
    if curProcess =0 then 
        let m = Matrix.create 20 25 2.
        MPI.sendMatrix (m,1,0)
        let p= MPI.receiveMatrix(1,0)
        printf "done"
                
    else
        
        let p= MPI.receiveMatrix(0,0)
        MPI.sendMatrix(p,0,0)
        //printf "%d %d"p.NumCols p.NumRows 
        

//MPI.logging := true    
sendreceiveArray()    
sendreceiveArrayDD()
sendreceiveDataSet()    
pingpong 100
sendreceiveMatrix()
funcTest()
sendreceiveMatrix2()

MPI.finalize()
